<?php
/**
 * @link https://ym2.cleverstone.top
 * @copyright Copyright (c) 2020 Yii Manager Software LLC
 */

namespace builder;

use Yii;
use builder\menu\MenuBuilder;
use builder\base\Builder;
use builder\tab\TabBuilder;
use builder\form\FormBuilder;
use builder\form_step\FormStepBuilder;
use builder\lists\ListBuilder;
use builder\tree\TreeBuilder;
use builder\table\TableBuilder;
use builder\tree_table\TreeTableBuilder;
use builder\base\ViewBuilderInterface;
use builder\base\InvalidInstanceException;
use builder\base\NotFoundParamsException;

/**
 * 视图构建器
 *
 * @property-read TableBuilder $table           表格构建器
 * @property-read TreeTableBuilder $treeTable   树表格构建器
 * @property-read FormBuilder $form             表单构建器
 * @property-read FormStepBuilder $formStep     分步表单构建器
 * @property-read ListBuilder $lists            列表构建器
 * @property-read TabBuilder $tab               选项卡构建器
 * @property-read TreeBuilder $tree             树组件构建器
 * @property-read MenuBuilder $menu             菜单组件构建器
 * @property boolean $partial                   是否局部视图渲染
 * @property string $alignThemePath             视图布局排列主题路径
 *
 * @author cleverstone
 * @since ym2.0
 */
class ViewBuilder extends Builder
{
    /**
     * @var string 视图构建器版本号
     */
    public $version = '2.0.0';

    /**
     * @var array 要渲染的视图集合
     */
    private $_viewRenders = [];

    /**
     * @var bool 是否局部视图渲染
     * @see $partial
     * @see setPartial()
     * @see getPartial()
     */
    private $_partial = false;

    /**
     * @var string 视图布局排列主题路径
     * @see $alignThemePath
     * @see setAlignThemePath()
     * @see getAlignThemePath()
     */
    private $_alignThemePath = '';

    /**
     * 设置视图布局排列主题路径
     * @param string $themePath 视图布局排列主题路径
     * @return $this
     */
    public function setAlignThemePath($themePath)
    {
        $this->_alignThemePath = (string)$themePath;
        return $this;
    }

    /**
     * 获取布局排列主题视图路径
     * @return string
     */
    public function getAlignThemePath()
    {
        return $this->_alignThemePath;
    }

    /**
     * 设置是否局部视图渲染
     * @param bool $boolean
     * @return $this
     */
    public function setPartial($boolean = true)
    {
        $this->_partial = $boolean;
        return $this;
    }

    /**
     * @return bool
     */
    public function getPartial()
    {
        return $this->_partial;
    }

    /**
     * 构建器名称
     * @return string
     */
    public function getName()
    {
        return 'view';
    }

    /**
     * @return string the view path that may be prefixed to a relative view name.
     */
    public function getViewPath()
    {
        return '';
    }

    /**
     * 视图渲染
     * @return string
     * @throws InvalidInstanceException
     * @throws NotFoundParamsException
     */
    public function render()
    {
        $builderId = $this->builderId;
        if ($builderId === null) {
            $result = [];
            foreach ($this->_viewRenders as $builder) {
                if ($builder instanceof ViewBuilderInterface) {
                    // 组件内容
                    array_push($result, $builder->render(true));
                } else {
                    throw new InvalidInstanceException('class ' . get_class($builder) . ' is not an instance of ' . ViewBuilderInterface::class);
                }
            }

            // 排列布局
            $content = implode("\n", $result);
            if (!empty($this->alignThemePath)) {
                $content = $this->_view->renderFile($this->alignThemePath, ['content' => $content], $this);
            }

            // 主布局
            return $this->_view->renderFile($this->partial ? $this->partialPath : $this->mainPath, ['content' => $content], $this);
        } else {
            foreach ($this->_viewRenders as $builder) {
                if (!$builder instanceof Builder) {
                    throw new InvalidInstanceException('class ' . get_class($builder) . ' is not an instance of ' . Builder::class);
                }

                if ($builderId == $builder->id) {
                    if ($builder instanceof ViewBuilderInterface) {
                        return $builder->render();
                    } else {
                        throw new InvalidInstanceException('class ' . get_class($builder) . ' is not an instance of ' . ViewBuilderInterface::class);
                    }
                }
            }
        }

        throw new NotFoundParamsException($this->idParam . ':' . $builderId);
    }

    /**
     * 获取表格构建器
     * @param array $config
     * @return TableBuilder
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getTable(array $config = [])
    {
        $tableBuilder = Yii::$container->get(TableBuilder::class, [], $config);
        array_push($this->_viewRenders, $tableBuilder);

        return $tableBuilder;
    }

    /**
     * 获取表单构建器
     * @param array $config
     * @return FormBuilder
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getForm(array $config = [])
    {
        $formBuilder = Yii::$container->get(FormBuilder::class, [], $config);
        array_push($this->_viewRenders, $formBuilder);

        return $formBuilder;
    }

    /**
     * 获取分步表单构建器
     * @param array $config
     * @return FormStepBuilder
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getFormStep(array $config = [])
    {
        $formStepBuilder = Yii::$container->get(FormStepBuilder::class, [], $config);
        array_push($this->_viewRenders, $formStepBuilder);

        return $formStepBuilder;
    }

    /**
     * 获取列表构建器
     * @param array $config
     * @return ListBuilder
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getLists(array $config = [])
    {
        $listBuilder = Yii::$container->get(ListBuilder::class, [], $config);
        array_push($this->_viewRenders, $listBuilder);

        return $listBuilder;
    }

    /**
     * 获取选项卡构建器
     * @param array $config
     * @return TabBuilder
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getTab(array $config = [])
    {
        $tabBuilder = Yii::$container->get(TabBuilder::class, [], $config);
        array_push($this->_viewRenders, $tabBuilder);

        return $tabBuilder;
    }

    /**
     * 获取树组件构建器
     * @param array $config
     * @return TreeBuilder
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getTree(array $config = [])
    {
        $treeBuilder = Yii::$container->get(TreeBuilder::class, [], $config);
        array_push($this->_viewRenders, $treeBuilder);

        return $treeBuilder;
    }

    /**
     * 获取菜单组件构建器
     * @param array $config
     * @return MenuBuilder
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getMenu(array $config = [])
    {
        $menuBuilder = Yii::$container->get(MenuBuilder::class, [], $config);
        array_push($this->_viewRenders, $menuBuilder);

        return $menuBuilder;
    }

    /**
     * 获取树表格构建器
     * @param array $config
     * @return TreeTableBuilder
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getTreeTable(array $config = [])
    {
        $treeTableBuilder = Yii::$container->get(TreeTableBuilder::class, [], $config);
        array_push($this->_viewRenders, $treeTableBuilder);

        return $treeTableBuilder;
    }
}